package com.gitee.liuzhi.design.create;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author liuzhi
 * @Date 2023/8/26 20:24
 * @Version 1.0
 * @Description 原型模式 Prototype Pattern
 * <p>
 * 原型模式是用于创建重复的对象, 同时又能保证性能
 * 这种模式实现了一个原型接口, 该接口用于创建当前对象的克隆, 当直接创建对象的代价比较大时, 则采用这种模式
 * <p>
 * 关键代码
 * 1. 实现 Cloneable 接口
 * 2. 重写 clone() 方法
 */
public class PrototypePattern {

    public static void main(String[] args) throws CloneNotSupportedException {
        Shape shape = ShapeCache.getShape("1");
        System.out.println(shape.getType());
        Shape shape2 = ShapeCache.getShape("2");
        System.out.println(shape2.getType());
        Shape shape3 = ShapeCache.getShape("3");
        System.out.println(shape3.getType());
    }

    /**
     * 创建 ShapeCache 类, 创建 Shape 实体对象, 存入类中的 HashMap 中
     */
    public static class ShapeCache {

        private static final Map<String, Shape> map = new HashMap(64) {{
            put("1", new Circle());
            put("2", new Square());
            put("3", new Rectangle());
        }};

        public static Shape getShape(String id) throws CloneNotSupportedException {
            Shape shape = map.get(id);
            return (Shape) shape.clone();
        }

    }


    /**
     * 实现了Cloneable的抽象形状类
     */
    @Data
    public abstract static class Shape implements Cloneable {

        private Long id;
        private String type;

        abstract void draw();

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    public static class Circle extends Shape {
        public Circle() {
            super.type = "圆形";
        }

        @Override
        void draw() {
            System.out.println("圆形");
        }
    }

    public static class Rectangle extends Shape {
        public Rectangle() {
            super.type = "长方形";
        }

        @Override
        void draw() {
            System.out.println("长方形");
        }
    }

    public static class Square extends Shape {
        public Square() {
            super.type = "正方形";
        }

        @Override
        void draw() {
            System.out.println("正方形");
        }
    }

}
